package com.rfid.project.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;

import biz.util.*;

import com.rfid.project.model.*;
import com.rfid.project.dao.*;
import com.rfid.project.exception.CannotDelException;
import com.rfid.project.exception.CannotUpdateException;
import com.mysema.query.BooleanBuilder;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
@Transactional
public class ProjectMemberService {

	@Autowired
	private ProjectMemberDao projectMemberDao;

	private QProjectMember $ = QProjectMember.projectMember;

	@Autowired
	public void setProjectMemberDao(ProjectMemberDao projectMemberDao) {
		this.projectMemberDao = projectMemberDao;
	}

	@Autowired
	private ProjectTaskPersonDao projetTaskPersonDao;

	private QProjectTaskPerson $_projectTaskPerson = QProjectTaskPerson.projectTaskPerson;

	@Autowired
	public void setProjetTaskPersonDao(ProjectTaskPersonDao projetTaskPersonDao) {
		this.projetTaskPersonDao = projetTaskPersonDao;
	}

	public List<ProjectMember> findAll() {
		return ListUtil.toList(projectMemberDao.findAll());
	}

	public List<ProjectMember> findAll(Long personId, Long projectId,
			Date planEnterDateBegin, Date planEnterDateEnd,
			Date planExitDateBegin, Date planExitDateEnd, String duty,
			Long projectMemberTypeId, Date createTimeBegin, Date createTimeEnd,
			Long createPersonId, String remark, String orderByAttribute) {
		BooleanBuilder condition = new BooleanBuilder();

		if (IdUtil.isNotEmpty(personId)) {
			condition.and($.person.id.eq(personId));
		}

		if (IdUtil.isNotEmpty(projectId)) {
			condition.and($.project.id.eq(projectId));
		}

		if (planEnterDateBegin != null) {
			condition.and($.planEnterDate.after(planEnterDateBegin));
		}

		if (planEnterDateEnd != null) {
			condition.and($.planEnterDate.before(planEnterDateEnd));
		}

		if (planExitDateBegin != null) {
			condition.and($.planExitDate.after(planExitDateBegin));
		}

		if (planExitDateEnd != null) {
			condition.and($.planExitDate.before(planExitDateEnd));
		}

		if (StringUtil.isNotEmpty(duty)) {
			condition.and($.duty.contains(duty));
		}

		if (IdUtil.isNotEmpty(projectMemberTypeId)) {
			condition.and($.projectMemberType.id.eq(projectMemberTypeId));
		}

		if (createTimeBegin != null) {
			condition.and($.createTime.after(createTimeBegin));
		}

		if (createTimeEnd != null) {
			condition.and($.createTime.before(createTimeEnd));
		}

		if (IdUtil.isNotEmpty(createPersonId)) {
			condition.and($.createPerson.id.eq(createPersonId));
		}

		if (StringUtil.isNotEmpty(remark)) {
			condition.and($.remark.contains(remark));
		}

		return ListUtil.toList(projectMemberDao.findAll(condition));
	}

	public Page<ProjectMember> findAll(Long departmentId, Long projectTypeId, Long projectSourceId, Long customerId, Long projectReportFrequencyId, String projectName, Long personId, Long projectId,
			String status, Date planEnterDateBegin, Date planEnterDateEnd,
			Date planExitDateBegin, Date planExitDateEnd, String duty,
			Long projectMemberTypeId, Date createTimeBegin, Date createTimeEnd,
			Long createPersonId, String remark, int pageNumber, int pageSize,
			String sortAttribute, String orderDirection) {
		BooleanBuilder condition = new BooleanBuilder();

		if(IdUtil.isNotEmpty(departmentId)){
			condition.and(this.$.project.department.id.eq(departmentId));
		}
		if(IdUtil.isNotEmpty(projectTypeId)){
			condition.and(this.$.project.projectType.id.eq(projectTypeId));
		}
		if(IdUtil.isNotEmpty(projectSourceId)){
			condition.and(this.$.project.projectSource.id.eq(projectSourceId));
		}
		if(IdUtil.isNotEmpty(customerId)){
			
		}
		if(IdUtil.isNotEmpty(projectReportFrequencyId)){
			condition.and(this.$.project.projectReportFrequency.id.eq(projectReportFrequencyId));
		}
		if (IdUtil.isNotEmpty(personId)) {
			condition.and($.person.id.eq(personId));
		}
		if (IdUtil.isNotEmpty(projectId)) {
			condition.and($.project.id.eq(projectId));
		}
		if (planEnterDateBegin != null) {
			condition.and($.planEnterDate.after(planEnterDateBegin));
		}

		if (planEnterDateEnd != null) {
			condition.and($.planEnterDate.before(planEnterDateEnd));
		}
		if (planExitDateBegin != null) {
			condition.and($.planExitDate.after(planExitDateBegin));
		}

		if (planExitDateEnd != null) {
			condition.and($.planExitDate.before(planExitDateEnd));
		}
		if (StringUtil.isNotEmpty(duty)) {
			condition.and($.duty.contains(duty));
		}
		if (IdUtil.isNotEmpty(projectMemberTypeId)) {
			condition.and($.projectMemberType.id.eq(projectMemberTypeId));
		}
		if (createTimeBegin != null) {
			condition.and($.createTime.after(createTimeBegin));
		}
		
		if (createTimeEnd != null) {
			condition.and($.createTime.before(createTimeEnd));
		}
		if (IdUtil.isNotEmpty(createPersonId)) {
			condition.and($.createPerson.id.eq(createPersonId));
		}
		
		if(StringUtil.isNotEmpty(projectName)){
			condition.and(this.$.project.name.contains(projectName));
		}
		if (StringUtil.isNotEmpty(remark)) {
			condition.and($.remark.contains(remark));
		}
		
		if(StringUtil.isNotEmpty(status)){
			condition.and(this.$.project.status.eq(status));
		}

		Sort sortObject = null;
		if (StringUtil.isEmpty(sortAttribute)) {
			sortObject = new Sort(Direction.ASC, "id");
		} else {
			sortObject = new Sort(Direction.fromStringOrNull(orderDirection), sortAttribute);
		}

		PageRequest pageRequest = new PageRequest(pageNumber - 1, pageSize, sortObject);
		return projectMemberDao.findAll(condition, pageRequest);
	}

	public ProjectMember getProjectMember(Long id) {
		return projectMemberDao.getOne(id);
	}

	public void deleteProjectMember(Long id) {
		projectMemberDao.delete(id);
	}
	
	public void deleteProjectMembers(Long projectId, Long[] personIds) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and(this.$.project.id.eq(projectId));
		condition.and(this.$.person.id.in(personIds));
		Iterable<ProjectMember> iterable = this.projectMemberDao.findAll(condition);
		for (ProjectMember projectMember : iterable) {
			if(this.findPersonTasksByProjectMember(projectMember)){
				continue;
			}
			projectMemberDao.delete(projectMember);
		}
	}
	
	private boolean findPersonTasksByProjectMember(ProjectMember projectMember){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and(this.$_projectTaskPerson.people.eq(projectMember.getPerson()));
		condition.and(this.$_projectTaskPerson.projectTask.project.eq(projectMember.getProject()));
		condition.or(this.$_projectTaskPerson.projectTask.taskCreator.eq(projectMember.getPerson()));
		return this.projetTaskPersonDao.count(condition) > 0;
	}

	public void saveProjectMember(ProjectMember projectMember) throws CannotUpdateException {
		if (null == projectMember.getCreateTime()) {
			projectMember.setCreateTime(DateUtil.nowDate());
		}
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($.projectMemberType.id.eq(10L));
		condition.and($.project.eq(projectMember.getProject()));
		Long count = this.projectMemberDao.count(condition);
		Long id = projectMember.getId();
		if (projectMember.getProjectMemberType().getId().equals(10L)) {
			if (count > 0) {
				if(null == id){
						throw new CannotUpdateException("该项目已分配项目经理职务，不能重复添加！");
				}else{
					ProjectMember temp = this.projectMemberDao.findOne(condition);
					if (!temp.getId().equals(projectMember.getId())) {
						throw new CannotUpdateException("该项目已分配项目经理职务，无法修改！");
					}
				}
			}
		}
		condition = new BooleanBuilder();
		condition.and($.project.eq(projectMember.getProject()));
		condition.and($.person.eq(projectMember.getPerson()));
		if (null == id) {
			count = this.projectMemberDao.count(condition);
			if (count > 0) {
				throw new CannotUpdateException("人员在该项目中已分配职务，无法添加！");
			}
		}
		projectMemberDao.save(projectMember);
	}
	public void saveProjectMember(Long projectId, Long[] personIds, People createPeople, Long ProjectMemberType) throws CannotUpdateException {
		ProjectMemberType projectMemberType = new ProjectMemberType();
		projectMemberType.setId(ProjectMemberType);
		Project project = new Project();
		project.setId(projectId);
		
		for (int i = 0, length = personIds.length; i < length; i++) {
			Long personId = personIds[i];
			
			BooleanBuilder condition = new BooleanBuilder();
			condition.and($.project.eq(project));
			condition.and(this.$.person.id.eq(personId));
			if(this.projectMemberDao.count(condition) < 1){
				People person = new People();
				person.setId(personId);
				
				ProjectMember projectMember = new ProjectMember();
				projectMember.setProject(project);
				projectMember.setCreatePerson(createPeople);
				projectMember.setProjectMemberType(projectMemberType);
				projectMember.setCreateTime(new Date());
				projectMember.setPerson(person);
				
				this.projectMemberDao.save(projectMember);
			}
		}
	}

	public Set<People> findProjectPeoplesByProject(Project project) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($.project.id.eq(project.getId()));
		List<ProjectMember> projectMembers = ListUtil
				.toList(this.projectMemberDao.findAll(condition));
		Set<People> peoples = new HashSet<People>();
		for (ProjectMember projectMember : projectMembers) {
			peoples.add(projectMember.getPerson());
		}
		return peoples;
	}

	public Set<People> findCreateProjectPeoplesByProject(Project project) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($.project.id.eq(project.getId()));
		List<ProjectMember> projectMembers = ListUtil
				.toList(this.projectMemberDao.findAll(condition));
		Set<People> peoples = new HashSet<People>();
		for (ProjectMember projectMember : projectMembers) {
			peoples.add(projectMember.getCreatePerson());
		}
		return peoples;
	}

	public Set<Project> findAllProjectByPeople(People people) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($.person.id.eq(people.getId()));
		List<ProjectMember> projectMembers = ListUtil
				.toList(this.projectMemberDao.findAll(condition));
		Set<Project> projects = new HashSet<Project>();
		for (ProjectMember projectMember : projectMembers) {
			projects.add(projectMember.getProject());
		}
		return projects;
	}

	/**
	 * 查找项目经理负责的所有项目
	 * @param people
	 * @return
	 */
	public Set<Project> findAllProjectByManager(People people) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($.person.id.eq(people.getId()));
		condition.and($.projectMemberType.id.eq(ProjectMemberType.MANAGER));
		List<ProjectMember> projectMembers = ListUtil.toList(this.projectMemberDao.findAll(condition));
		Set<Project> projects = new HashSet<Project>();
		for (ProjectMember projectMember : projectMembers) {
			projects.add(projectMember.getProject());
		}
		return projects;
	}
	
	
	/**
	 * 查找作为普通成员参与的项目
	 * @param people
	 * @return
	 */
	public Set<Project> findAllProjectByMember(People people) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($.person.id.eq(people.getId()));
		condition.and($.projectMemberType.id.eq(ProjectMemberType.MEMBER));
		List<ProjectMember> projectMembers = ListUtil
				.toList(this.projectMemberDao.findAll(condition));
		Set<Project> projects = new HashSet<Project>();
		for (ProjectMember projectMember : projectMembers) {
			projects.add(projectMember.getProject());
		}
		return projects;
	}
	
	
	public Set<People> findCreateProjectPeoplesByPeople(People people) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($.createPerson.eq(people));
		List<ProjectMember> projectMembers = ListUtil
				.toList(this.projectMemberDao.findAll(condition));
		Set<People> peoples = new HashSet<People>();
		for (ProjectMember projectMember : projectMembers) {
			peoples.add(projectMember.getCreatePerson());
		}
		return peoples;
	}
	
	public long findPeopleCount(Project project){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and(this.$.project.eq(project));
		return this.projectMemberDao.count(condition);
	}
	
	public Set<People> findPeoplesByProject(Project project, ProjectMemberType projectMemberType){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and(this.$.project.eq(project));
		condition.and(this.$.projectMemberType.eq(projectMemberType));
		List<ProjectMember> projectMembers = ListUtil.toList(this.projectMemberDao.findAll(condition));
		Set<People> peoples = new HashSet<People>();
		for (ProjectMember projectMember : projectMembers) {
			peoples.add(projectMember.getPerson());
		}
		return peoples;
	}

	public void saveProjectMember(Long projectId, Long personId, Long ProjectMemberType) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and(this.$.project.id.eq(projectId));
		condition.and(this.$.person.id.eq(personId));
		List<ProjectMember> projectMembers = ListUtil.toList(this.projectMemberDao.findAll(condition));
		if(!projectMembers.isEmpty()){
			ProjectMember projectMember = projectMembers.get(0);
			
			ProjectMemberType projectMemberType = new ProjectMemberType();
			projectMemberType.setId(ProjectMemberType);
			
			projectMember.setProjectMemberType(projectMemberType);
			this.projectMemberDao.save(projectMember);
		}
	}

	public void deleteProjectMembers(Long id) throws CannotDelException {
		ProjectMember projectMember = this.projectMemberDao.findOne(id);
		if (this.findPersonTasksByProjectMember(projectMember)) {
			throw new CannotDelException("人员已分配任务，无法删除！");
		}
		this.projectMemberDao.delete(id);
	}

	public Long getPeopleCountByProject(Project project) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and(this.$.project.eq(project));
		return this.projectMemberDao.count();
	}

	public ProjectMember findOne(Long id) {
		return this.projectMemberDao.findOne(id);
	}

}
